import { reactive, watch, ref, onBeforeUnmount, getCurrentInstance, onMounted, nextTick, provide } from "vue"
import { loadStyleString, unLoadStyle, createCancellablePromise, convertValue, isContainerEle, getFuncFromString, withExtraParams } from "./useUtil"
import TaskQueue from "@/utils/taskQueue"

enum Hooks {
  CREATED = 'Created',
  MOUNTED = 'Mounted',
  UNMOUNTED = 'Unmounted',
  ACTIVATED = 'Activated',
  DEACTIVATED = 'Deactivated'
}

export default function useConfig(props: any) {

  const { promise, cancel } = createCancellablePromise()

  const instance = getCurrentInstance()
  provide('pmInstance', instance)
  const taskQueue = new TaskQueue(1)

  const myConfig = reactive<Record<string, any>>({})
  const models = reactive<Record<string, any>>({})
  const itemInfos = reactive<Record<string, any>>({})
  const loading = ref(false)

  watch(
    () => props.config,
    (newVal) => {
      loading.value = true
      if (newVal && JSON.stringify(newVal) !== '{}') {
        Object.assign(myConfig, JSON.parse(JSON.stringify(newVal)))
        taskQueue.addTask(() => handleConfig(), 1)
        // 将之前的promise取消掉
        cancel()
      } else {
        // 等待
        if (!taskQueue.isRunning) {
          taskQueue.addTask(async () => await promise)
        }
      }
    },
    {
      immediate: true
    }
  )

  async function handleConfig() {
    try {
      if (myConfig.config && myConfig.config.style && myConfig.config.style.pageStyle) {
        // 加载样式
        loadStyleString(props.code, myConfig.config.style.pageStyle)
      }
      generateList(myConfig.list)
      await nextTick()
      await executeHook(Hooks.CREATED)
      handleAddWatcher()
    } catch (error) {
      
    }
    loading.value = false
  }

  function generateList(list: any[]) {
    for (const item of list) {
      if (isContainerEle(item.component)) {
        if (item.columns) {
          item.columns.forEach((col: any) => {
            generateList(col.list)
          })
        }
      } else if (item.component !== 'eButton') {
        if (props.modelValue && Object.keys(props.modelValue).includes(item.model)) {
          models[item.model] = props.modelValue[item.model]
        } else {
          models[item.model] = convertValue(item)
        }
        itemInfos[item.model] = item
      }
    }
  }

  async function executeHook(type: Hooks) {
    if (myConfig && myConfig.config && myConfig.config.lifeCircle) {
      const hook = myConfig.config.lifeCircle[`${type}Hook`] || ''
      if (hook && hook.includes('function')) {
        getFuncFromString(hook).call(null, instance?.exposed)
      }
    }
    return null
  }

  function handleAddWatcher() {
    if (myConfig && myConfig.config && myConfig.config.watch) {
      const watchers = myConfig.config.watch.watchers || []
      for (const item of watchers) {
        if (item.key && item.watchFunc && item.watchFunc.includes('function')) {
          const config = (item.config || []).reduce((prev: Record<string, boolean>, cur: string) => {
            prev[cur] = true
            return prev
          }, {})
          watch(
            () => eval(item.key),
            withExtraParams(getFuncFromString(item.watchFunc), instance?.exposed),
            config
          )
        }
      }
    }
  }

  onMounted(() => {
    taskQueue.addTask(() => executeHook(Hooks.MOUNTED))
  })

  onBeforeUnmount(() => {
    // 销毁样式
    unLoadStyle(props.code)
    taskQueue.addTask(() => executeHook(Hooks.UNMOUNTED))
  })

  return {
    myConfig,
    models,
    itemInfos,
    loading
  }
}